<?php

/**
 * Description of CartManager
 *
 * @author Vicente, Maximiliano
 */
class VentasManager {

    private static $instancia;
    private $nro_factura;
    private $iva;
    private $fecha;
    private $cliente;
    private $tipo;
    private $descuento;
    private $detalle_venta;

    const CANT_MINIMA=1;

    /**
     * Metodo que asegura que siempre se acceda a una única instancia del objeto
     * @param --
     * @author
     * @return instancia
     */
    static public function getInstance() {
        if (!self::$instancia instanceof self) {
            self::$instancia = new self;
        }
        return self::$instancia;
    }

    /**
     * Constructor
     * @param --
     * @author
     * @return --
     */
    private function __construct() {

        $descuento = $this->setDescuento(sfConfig::get('app_descuento'));
        $iva = sfConfig::get('app_iva');

        $this->setIva($iva);
        $this->setDescuento($descuento);
    }

    //Propiedades de la clase
    public function getIva() {
        return $this->iva;
    }

    public function getNroFactura() {
        return $this->nro_factura;
    }

    public function getCliente() {
        return $this->cliente;
    }

    public function getFecha() {
        return $this->fecha;
    }

    public function getDescuento() {
        return $this->descuento;
    }

    public function setIva($iva) {

        if (!empty($iva)) {
            $this->iva = $iva;
            return $this->iva;
        }
        return null;
    }

    public function setNroFactura($nroFactura) {

        if (!empty($nroFactura)) {
            $this->nro_factura = $nroFactura;
            return $this->nro_factura;
        }
        return null;
    }

    public function setCliente(Clientes $cliente) {

        if (!empty($cliente)) {
            $this->cliente = $cliente;
            return $this->cliente;
        }
        return null;
    }

    public function setFecha() {
        try {
            $fecha = gmdate('Y-m-d');
            $this->fecha = $fecha;
            return $this->fecha;
        } catch (sfException $e) {
            return null;
        }
    }

    public function setDescuento($descuento) {

        if (!empty($descuento)) {
            $this->descuento = $descuento;
            return $this->descuento;
        }
        return null;
    }

    /**
     * Constructor
     * @param producto Producto, cantidad a agregar
     * @author
     * @return bool; true si no hubo errores, false en cualquier otro caso
     */
    public function cargarCarro($producto, $cantidad) {

        try {
            $carro = sfContext::getInstance()->getUser()->getAttribute('venta');
            if (!empty($producto)) {
                $articulo = $producto->getProArticulo();
                $talle = $producto->getProTalle();

                $carro["productos"][$articulo . '.' . $talle]["producto"] = $producto;
                $carro["productos"][$articulo . '.' . $talle]["cantidad"] = $cantidad;

                sfContext::getInstance()->getUser()->setAttribute('venta', $carro);
                return true;
            }
        } catch (sfException $e) {
            return false;
        }
    }

    /**
     * Agrega un producto a la venta
     * @param objeto Productos
     * @author
     * @return --
     */
    public function agregarProducto(Productos $producto, $cantidad=1) {

        try {

            $carro = sfContext::getInstance()->getUser()->getAttribute('venta');

            //Producto no es vacio
            if (!empty($producto)) {

                $articulo = $producto->getProArticulo();
                $talle = $producto->getProTalle();
                $ganancia = $producto->getProGanancia();
                $disponibilidad = $producto->getProDisponible();

                //Producto existe?
                if ($this->productoExiste($producto)) {

                    //Existe
                    //Hay unidades disponibles?Entones se adhiere una unidad más
                    if ($disponibilidad > $carro["productos"][$articulo . '.' . $talle]["cantidad"]) {

                        $cantCarro = $carro["productos"][$articulo . '.' . $talle]["cantidad"];
                        $cantCarro = $cantCarro + $cantidad;
                        $carro["productos"][$articulo . '.' . $talle]["cantidad"] = $cantCarro;

                        sfContext::getInstance()->getUser()->setAttribute('venta', $carro);
                        return true;
                    }
                    return false;
                } else {

                    //NO Existe, hay disponibles? Entonces se adhiere producto y cantidad = 1
                    if ($disponibilidad > 0) {
                        //implementacion objeto DetalleVentas
                        //new DetalleVenta($producto,$cantidad);
                        //implementacion array
                        $carro["productos"][$articulo . '.' . $talle]["producto"] = $producto;
                        $carro["productos"][$articulo . '.' . $talle]["cantidad"] = $cantidad;
                        sfContext::getInstance()->getUser()->setAttribute('venta', $carro);
                        return true;
                    }
                    return false;
                }
            }
        } catch (sfException $e) {
            return false;
        }
    }

    public function esDisponible(Productos $producto) {
        $carro = sfContext::getInstance()->getUser()->getAttribute('venta');
        $disponibilidad = $producto->getProDisponible();
        $articulo = $producto->getProArticulo();
        $talle = $producto->getProTalle();
        
        
        if ($this->productoExiste($producto)) {
            $cantidad_carro = $carro["productos"][$articulo . '.' . $talle]["cantidad"];
            if ($disponibilidad > 0 && $disponibilidad > $cantidad_carro) {
                return true;
            }
        } else {
            if ($disponibilidad > 0) {
                return true;
            }
        }
        return false;
    }

    /**
     * Chequea la existencia del producto en la venta
     * @param objeto Productos
     * @author
     * @return true/false
     */
    public function productoExiste(Productos $producto) {

        $carro = sfContext::getInstance()->getUser()->getAttribute('venta');
        if (!empty($producto)) {

            $articulo = $producto->getProArticulo();
            $talle = $producto->getProTalle();

            if (!empty($carro)) {
                $productoCarro = array_key_exists($articulo . '.' . $talle, $carro["productos"]);

                if (!empty($productoCarro)) {
                    return true;
                }
            }
        }
        return false;
    }

    public function comprobarPago() {
        $tipo_pago = $this->getFormasDePago();
        //Si el pago es únicamente con efectivo, comprobar total de pago con total de venta con decuento
        if (!array_key_exists('cheque', $tipo_pago) && !array_key_exists('tarjeta', $tipo_pago)
                && !array_key_exists('cta_cte', $tipo_pago) && array_key_exists('efectivo', $tipo_pago)) {
            $total_venta = $this->getPrecioVentaConDescuento();
            $pago = ($tipo_pago['efectivo'] == $total_venta) ? true : false;
            return $pago;
        } else {
            //De lo contrario, compara con el precio de venta sin descuento
            // Esta emparchada es porque solo pasa como índices del array aquellos
            // métodos de pago que fueron seleccionados. Si por ejemplo no se selecciona
            // cheque revienta diciendo index cheque undefined.
            if (!isset($tipo_pago['cheque'])) {
                $tipo_pago['cheque'] = 0;
            }
            if (!isset($tipo_pago['tarjeta'])) {
                $tipo_pago['tarjeta'] = 0;
            }
            if (!isset($tipo_pago['cuotas'])) {
                $tipo_pago['cuotas'] = 0;
            }
            if (!isset($tipo_pago['cta_cte'])) {
                $tipo_pago['cta_cte'] = 0;
            }
            $precioaPagar = $tipo_pago['efectivo'] + $tipo_pago['cheque'] + ($tipo_pago['tarjeta'] * $tipo_pago['cuotas']) + $tipo_pago['cta_cte'];
            $total_venta = $this->getPrecioFinal();
            $pago = ($precioaPagar === $total_venta) ? true : false;
            return $pago;
        }
    }

    /**
     * Elimina un producto de la venta
     * @param objeto Producto
     * @author
     * @return --
     */
    public function eliminarProducto(Productos $producto) {

        $carro = sfContext::getInstance()->getUser()->getAttribute('venta');

        if (!empty($producto)) {

            unset($carro["productos"][$producto->getProArticulo() . '.' . $producto->getProTalle()]);
            sfContext::getInstance()->getUser()->setAttribute('venta', $carro);
            return true;
        }
        return false;
    }

    /**
     * Disminuye la cantidad del producto en la venta
     * @param objeto Productos
     * @author
     * @return true/false
     */
    public function eliminarCantProducto(Productos $producto) {

        $cantidad = self::CANT_MINIMA;

        try {
            $carro = sfContext::getInstance()->getUser()->getAttribute('venta');

            if (!empty($producto)) {
                if (!empty($carro)) {
                    $cantCarro = $carro["productos"][$producto->getProArticulo() . '.' . $producto->getProTalle()]["cantidad"];

                    $cantCarro = $cantCarro - $cantidad;
                    $carro["productos"][$producto->getProArticulo() . '.' . $producto->getProTalle()]["cantidad"] = $cantCarro;

                    if ($cantCarro == 0) {
                        unset($carro["productos"][$producto->getProArticulo() . '.' . $producto->getProTalle()]);
                    }
                }

                sfContext::getInstance()->getUser()->setAttribute('venta', $carro);
                return true;
            }
        } catch (sfException $e) {
            return false;
        }
    }

    /**
     * Elimina todos los productos de la venta
     * @param --
     * @author
     * @return --
     */
    public function vaciarCarro() {
        sfContext::getInstance()->getUser()->setAttribute('venta', null);
    }

    /**
     * Comprueba si el carro está vacío
     * @param --
     * @author
     * @return true/false
     */
    public function estaVacio() {
        $carro = sfContext::getInstance()->getUser()->getAttribute('venta');

        if (empty($carro["productos"])) {
            return true;
        }
        return false;
    }

    /**
     * Autogenera el numero de factura de la venta
     * @param tipo de Venta
     * @author
     * @return --
     */
    public function autogenerarNroFactura($tipoVta) {

        $venta = VentasPeer::obtenerUltimaVenta($tipoVta);

        try {
            if (!empty($venta)) {
                $longitudNroFact = 10;

                //Obtener nro Factura
                $nroFactura = $venta->getVtaNroFactura();

                //Dividir entre el nro sucursal y nro factura
                $nro = explode('-', $nroFactura);
                $nroCasa = $nro[0];
                $nroFact = intval($nro[1]) + 1;

                $numbersNoZero = '123456789';
                $nroDocNoZero = strpbrk($nroFact, $numbersNoZero);
                $zero = '0';
                $nroDocZeros = str_repeat($zero, $longitudNroFact - strlen($nroFact));

                $nroDoc = $nroDocZeros . $nroDocNoZero;
                return $nroFactura = $nroCasa . '-' . $nroDoc;
            } else {

                $nroCasa = '0000';
                $nroDoc = '0000000001';
                $nroFactura = $nroCasa . '-' . $nroDoc;

                return $nroFactura;
            }
        } catch (sfException $e) {
            return false;
        }
    }

    /**
     * Establece la forma de pago de la venta
     * @param precios de formas de pago
     * @author
     * @return --
     */
    public function setFormasDePago($precioEfectivo=null, $precioCheque=null, $precioCtaCte=null, $precioTarjeta=null, $cuotasTarjeta=null) {

        try {
            $venta = sfContext::getInstance()->getUser()->getAttribute('venta');
            $venta["pagos"] = null;
            if (!empty($precioEfectivo)) {
                $venta["pagos"]["efectivo"] = $precioEfectivo;
            }
            if (!empty($precioCheque)) {
                $venta["pagos"]["cheque"] = $precioCheque;
            }
            if (!empty($precioCtaCte)) {
                $venta["pagos"]["cta_cte"] = $precioCtaCte;
            }
            if (!empty($precioTarjeta)) {
                $venta["pagos"]["tarjeta"] = $precioTarjeta;
                $venta["pagos"]["cuotas"] = $cuotasTarjeta;
            }

            sfContext::getInstance()->getUser()->setAttribute('venta', $venta);

            return true;
        } catch (sfException $e) {
            return false;
        }
    }

    /**
     * Obtener la forma de pago de la venta
     * @param --
     * @author
     * @return --
     */
    public function getFormasDePago() {
        try {
            $venta = sfContext::getInstance()->getUser()->getAttribute('venta');
            return $venta["pagos"];
        } catch (sfException $e) {
            return false;
        }
    }

    /**
     * Obtiene el total a pagar por el cliente mediante las distintas formas de pago
     * @param precios de formas de pago
     * @author
     * @return formas de pago
     */
    public function getTotalFormaDePago($precioEfectivo=null, $precioCheque=null, $precioCtaCte=null, $precioTarjeta=null, $cuotasTarjeta=null) {

        try {
            $totalPago = 0;
            if (!empty($precioEfectivo)) {
                $totalPago += $precioEfectivo;
            }
            if (!empty($precioCheque)) {
                $totalPago += $precioCheque;
            }
            if (!empty($precioCtaCte)) {
                $totalPago += $precioCtaCte;
            }
            if (!empty($precioTarjeta) && !empty($precioTarjeta)) {
                $totalTarjeta = $precioTarjeta * $cuotasTarjeta;
                $totalPago += $totalTarjeta;
            }

            return $totalPago;
        } catch (sfException $e) {
            return false;
        }
    }

    /**
     * Obtiene el subtotal de la venta
     * @param --
     * @author
     * @return subtotal de la venta
     */
    public function getSubtotal() {
        $carro = sfContext::getInstance()->getUser()->getAttribute('venta');

        if (!empty($carro)) {
            $total = 0;
            foreach ($carro["productos"] as $producto) {
                $prod = $producto["producto"];
                $cant = $producto["cantidad"];

                $precioTotal = round($prod->getPrecioVenta(), 2);
                $total+=round($precioTotal * $cant, 2);
            }

            return $total;
        }
        return false;
    }

    /**
     * Obtiene el precio final
     * @param --
     * @author
     * @return total de la venta
     */
    public function getPrecioFinal() {

        $subtotal = $this->getSubtotal();
        $carro = sfContext::getInstance()->getUser()->getAttribute('venta');

        if (!empty($carro["pagos"])) {
            $esEfectivo = array_key_exists("efectivo", $carro["pagos"]);
            $esCheque = array_key_exists("cheque", $carro["pagos"]);
            $esCtaCte = array_key_exists("cta_cte", $carro["pagos"]);
            $esTarjeta = array_key_exists("tarjeta", $carro["pagos"]);


            if (!empty($subtotal)) {
                if ($esEfectivo && !$esCheque && !$esCtaCte && !$esTarjeta) {
                    //$desc = DescuentosPeer::doSelectOne(new Criteria());
                    $desc = sfConfig::get('app_descuento');

                    if (!empty($desc)) {
                        $porcDescuento = $desc / 100;
                        $precioFinal = round($subtotal - ($subtotal * $porcDescuento), 2);

                        return $precioFinal;
                    }
                }
                return $subtotal;
            }
        }
        return null;
    }

    /**
     * Obtiene el precio de venta con descuento
     * @param --
     * @author
     * @return total de la venta con descuento
     */
    public function getPrecioVentaConDescuento() {

        $subtotal = $this->getSubtotal();
        $desc = sfConfig::get('app_descuento');

        if (!empty($desc)) {
            $porcDescuento = $desc / 100;
            $precioFinal = round($subtotal - ($subtotal * $porcDescuento), 2);

            return $precioFinal;
        }
        return false;
    }

    /**
     * Obtiene el precio de venta sin descuento
     * @param --
     * @author
     * @return total de la venta sin descuento
     */
    public function getPrecioVentaSinDescuento() {

        try {
            $subtotal = $this->getSubtotal();
            return round($subtotal, 2);
        } catch (sfException $e) {
            return false;
        }
    }

}

?>
